#include "../include/server.h"
#include "../include/myjson.h"

static int server_sockfd = 0;
static char infomsg_err[128] = {0}; // 定义一个字符串，用于返回错误信息

static char server_ip[20] = {0};
static int server_port = 0;

int set_server_ip(const char *ip)
{
	strcpy(server_ip, ip);
	return 0;
}

int set_server_port(int port)
{
	server_port = port;
	return 0;
}

void set_infomsg_err(char *buf)
{
	if (buf == NULL)
		return;

	memset(infomsg_err, 0, sizeof(infomsg_err));
	strcpy(infomsg_err, buf);
}

char *get_infomsg_err()
{
	return infomsg_err;
}

int get_serversockfd()
{
	return server_sockfd;
}

int server_init()
{
	// 创建套接字
	if ((server_sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
		ERR_LOG("socket error ");

	// 填充网络信息结构体
	struct sockaddr_in serveraddr;
	memset(&serveraddr, 0, sizeof(serveraddr));
	serveraddr.sin_family = AF_INET;
	serveraddr.sin_addr.s_addr = inet_addr(server_ip);
	serveraddr.sin_port = htons(server_port);
	socklen_t serveraddr_len = sizeof(serveraddr);

	// setsockopt设置端口复用------------
	int val = 1;
	socklen_t val_len = sizeof(val);
	if (setsockopt(server_sockfd, SOL_SOCKET, SO_REUSEADDR, &val, val_len) == -1)
		ERR_LOG("setsockopt error");

	// 绑定
	if (bind(server_sockfd, (struct sockaddr *)&serveraddr, serveraddr_len) == -1)
		ERR_LOG("bind error ");

	// 开始监听
	if (listen(server_sockfd, 5) == -1)
		ERR_LOG("listen error");

	printf("sockfd_init success!  %s:%d\n", server_ip, server_port);

	return server_sockfd;
}

int server_accept(struct sockaddr_in *clientaddr)
{
	int acceptfd;
	memset(clientaddr, 0, sizeof(struct sockaddr_in));
	socklen_t clientaddr_len = sizeof(struct sockaddr_in);

	if ((acceptfd = accept(server_sockfd, (struct sockaddr *)clientaddr, &clientaddr_len)) == -1)
		ERR_LOG("accept error!");

	INFO_LOG("\n\t客户端 %s:%d fd = %d 连接成功\n", inet_ntoa((*clientaddr).sin_addr),
			 ntohs((*clientaddr).sin_port), acceptfd);

	return acceptfd;
}

/**
 * 接收到字符串，解析成结构体
 * 返回0解析成功，-1解析失败
 */
int recv_json_to_struct(list_t *clinode, msg_t *clientmsg)
{
	if (clinode == NULL || clientmsg == NULL)
		return -1;

	char *recvbuf = (char *)malloc(4 * 1024);
	memset(recvbuf, 0, sizeof(4 * 1024));
	int recvlen = 0;
	char *temp = recvbuf;
	do
	{
		recvlen = recv(clinode->client_sockfd, temp, 4096, 0);
		if (recvlen == -1)
		{
			ERR_PRIENT("recv error");
			goto err;
		}
		else if (recvlen == 0)
		{
			ERR_PRIENT("client close");
			goto err;
		}

		temp += recvlen;
	} while (is_valid_json(recvbuf)); 

	// 确认是json则转换成结构体
	if (json_to_struct(recvbuf, clientmsg) != 0)
	{
		INFO_LOG("json is not to struct!");
		goto err;
	}
	strncpy(clientmsg->pcjsonbuf, recvbuf, sizeof(clientmsg->pcjsonbuf));

	free(recvbuf);
	return 0;

err:
	free(recvbuf);
	return -1;
}

/**
 * 将json，解析成结构体
 * 返回0解析成功，-1解析失败
 */
int json_to_struct(char *json_string, msg_t *climsg)
{
	cJSON *json = cJSON_Parse(json_string);
	if (json != NULL)
	{
		// 提取并输出各个键值对的值
		cJSON *ID = cJSON_GetObjectItem(json, "ID");		//必须
		if (ID != NULL)
		{
			strcpy(climsg->ID, ID->valuestring);
		}
		else
		{
			INFO_LOG("Not find ID");
			goto err;
		}

		cJSON *PS = cJSON_GetObjectItem(json, "PW");		
		if (PS != NULL)
		{
			strcpy(climsg->PS, PS->valuestring);
		}

		cJSON *cmd = cJSON_GetObjectItem(json, "cmd");
		if (cmd != NULL)
		{
			climsg->cmd = cmd->valueint;
		}

		cJSON *flags = cJSON_GetObjectItem(json, "flag");
		if (flags != NULL)
		{
			climsg->flags = flags->valueint;
		}

		cJSON *device_id = cJSON_GetObjectItem(json, "devNo");	//必须
		if (device_id != NULL)
		{
			strcpy(climsg->device_id, device_id->valuestring);
		}
		else
		{
			INFO_LOG("Not find device_id");
			goto err;
		}

		cJSON *msgtype = cJSON_GetObjectItem(json, "msgType");	//必须
		if (msgtype != NULL)
		{
			climsg->msgtype = msgtype->valueint;
		}
		else
		{
			INFO_LOG("Not find msgtype");
			goto err;
		}

		// 设备控制命令
		cJSON *device_ctrl = cJSON_GetObjectItem(json, "device_ctrl");
		if (device_ctrl != NULL)
		{
			climsg->device_ctrl = device_ctrl->valueint;
		}

		// 删除JSON对象以释放内存
		cJSON_Delete(json);
		return 0;
	}
	else
	{
		const char *error_ptr = cJSON_GetErrorPtr();
		if (error_ptr != NULL)
		{
			fprintf(stderr, "Error before: %s\n", error_ptr);
		}
	}

err:
	cJSON_Delete(json);
	return -1;
}

int struct_to_json(char *json_string, msg_t *climsg)
{
}
